<template>
  <div id="map"></div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import chinaJson from '../assets/china.json';
import jxsJson from '../assets/jxs.json';
import * as THREE from 'three';
import {
  CSS2DRenderer,
  CSS2DObject,
} from 'three/examples/jsm/renderers/CSS2DRenderer.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import * as d3 from 'd3';
import { Reflector } from 'three/examples/jsm/objects/Reflector.js';
import {
  CSS3DRenderer,
  CSS3DObject,
} from 'three/examples/jsm/renderers/CSS3DRenderer.js';
import localTexture1 from '../assets/digitalGround1.png?url';
import localTexture2 from '../assets/digitalGround2.png?url';
import localTexture3 from '../assets/digitalGround3.png?url';
import localTexture4 from '../assets/digitalGround4.png?url';
import imgFloor1Texture from '../assets/imgFloor1.png?url';
import imgFloor2Texture from '../assets/imgFloor2.png?url';
import imgFloor3Texture from '../assets/imgFloor3.png?url';
import shotTextrue from '../assets/shot.png?url';
import { Pane } from 'tweakpane';
let map, renderer, scene, camera, controls, labelRenderer, label3DRenderer;
let imgFloor1, imgFloor2, imgFloor3;
let zooming = true; // 控制是否进行运镜动画
let zoomDuration = 4000; // 动画持续时间（毫秒）
let zoomStartTime = null;
let nanChangPosition, ganyuPosition;
let mapDome;
let guangdai;
const offsetXY = d3.geoMercator();

// 以北京为中心 修改坐标
let projection;

onMounted(() => {
  projection = d3
    .geoMercator()
    .center([116.412318, 39.909843])
    .translate([0, 0]);

    
  createScene();
  createCamera();
  createLight();
  // createFoold();
  // makeMesh();
  // createJXMapAopu();
  // createRotateBase();
  createRanderrer();
  // createAxis();
  createControls();
  // createGeometry();
  // initGUI();
  animate();
  // createLineTop();

  makeMap();
  const line = lineConnect(projection([106.557691, 29.559296]), projection([121.495721, 31.236797]))
      scene.add(line)
      const line2 = lineConnect(projection([106.557691, 29.559296]), projection([104.006215, 30.650055]))
      scene.add(line2)
      const line3 = lineConnect(projection([106.557691, 29.559296]), projection([116.396795, 39.93242]))
      scene.add(line3)
      const line4 = lineConnect(projection([106.557691, 29.559296]), projection([87.617099, 43.863737]))
      scene.add(line4)
      
});

const makeMap = () => {
  // const loader = new THREE.FileLoader();
   const url = 'https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json';
  fetch(url)
    .then((res) => res.json())
    .then((data) => {
      operationData(data);
    });
};

// 解析数据
function operationData(jsondata) {
    map = new THREE.Object3D()
  // 全国信息
  const features = jsondata.features;
  features.forEach((feature) => {
    // 单个省份 对象
    const province = new THREE.Object3D();
    // 地址
    province.properties = feature.properties.name;
    const coordinates = feature.geometry.coordinates;
    const color = 'yellow';
    // const color = ['重庆市', '上海市'].includes(feature.properties.name) ? 'blue' : 'yellow'

    if (feature.geometry.type === 'MultiPolygon') {
      // 多个，多边形
      coordinates.forEach((coordinate) => {
        // coordinate 多边形数据
        coordinate.forEach((rows) => {
          const mesh = drawExtrudeMesh(rows, color);
          const line = lineDraw(rows, color);
          province.add(line);
          province.add(mesh);
        });
      });
    }

    if (feature.geometry.type === 'Polygon') {
      // 多边形
      coordinates.forEach((coordinate) => {
        const mesh = drawExtrudeMesh(coordinate, color);
        const line = lineDraw(coordinate, color);
        province.add(line);
        province.add(mesh);
      });
    }
    map.add(province);
  });
  scene.add(map);
}

function drawExtrudeMesh(polygon, color) {
  const shape = new THREE.Shape();
  // polygon.forEach((row, i) => {
  //   const [x, y] = [row[0], row[1]]
  //   if (i === 0) {
  //     shape.moveTo(x, y)
  //   }
  //   shape.lineTo(x, y)
  // })
  polygon.forEach((row, i) => {
    const [x, y] = projection(row);
    if (i === 0) {
      shape.moveTo(x, -y);
    }
    shape.lineTo(x, -y);
  });

  // 拉伸
  const geometry = new THREE.ExtrudeGeometry(shape, {
    depth: 10,
    bevelEnabled: false,
  });
  const material = new THREE.MeshBasicMaterial({
    color: color,
    transparent: true,
    opacity: 0.5,
  });
  return new THREE.Mesh(geometry, material);
}
function lineDraw(polygon, color) {
  const lineGeometry = new THREE.BufferGeometry();
  const pointsArray = new Array();
  polygon.forEach((row) => {
    const [x, y] = projection(row);
    // 创建三维点
    pointsArray.push(new THREE.Vector3(x, -y, 9));
  });
  // 放入多个点
  lineGeometry.setFromPoints(pointsArray);

  const lineMaterial = new THREE.LineBasicMaterial({
    color: color,
  });
  return new THREE.Line(lineGeometry, lineMaterial);
}

   /**
       * 两点链接飞线
       * */
      function lineConnect(posStart, posEnd) {
        // 根据目标坐标设置3D坐标  z轴位置在地图表面
        const [x0, y0, z0] = [...posStart, 10.01]
        const [x1, y1, z1] = [...posEnd, 10.01]

        // 使用QuadraticBezierCurve3() 创建 三维二次贝塞尔曲线
        const curve = new THREE.QuadraticBezierCurve3(
          new THREE.Vector3(x0, -y0, z0),
          new THREE.Vector3((x0 + x1) / 2, -(y0 + y1) / 2, 20),
          new THREE.Vector3(x1, -y1, z1)
        )

        // 绘制 目标位置
        spotCircle([x0, y0, z0])
        spotCircle([x1, y1, z1])
        moveSpot(curve)

        const lineGeometry = new THREE.BufferGeometry()
        // 获取曲线 上的50个点
        var points = curve.getPoints(50)
        var positions = []
        var colors = []
        var color = new THREE.Color()

        // 给每个顶点设置演示 实现渐变
        for (var j = 0; j < points.length; j++) {
          color.setHSL(0.81666 + j, 0.88, 0.715 + j * 0.0025) // 粉色
          colors.push(color.r, color.g, color.b)
          positions.push(points[j].x, points[j].y, points[j].z)
        }
        // 放入顶点 和 设置顶点颜色
        lineGeometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3, true))
        lineGeometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3, true))

        const material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors, side: THREE.DoubleSide })
        const line = new THREE.Line(lineGeometry, material)

        return line
      }

      // 圆环网格对象组
      const circleYs = []
      /**
       * 目标位置
       * */
      function spotCircle(spot) {
        // 圆
        const geometry1 = new THREE.CircleGeometry(0.5, 200)
        const material1 = new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide })
        const circle = new THREE.Mesh(geometry1, material1)
        // 绘制地图时 y轴取反 这里同步
        circle.position.set(spot[0], -spot[1], spot[2] + 0.1)
        scene.add(circle)

        // 圆环
        const geometry2 = new THREE.RingGeometry(0.5, 0.7, 50)
        // transparent 设置 true 开启透明
        const material2 = new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide, transparent: true })
        const circleY = new THREE.Mesh(geometry2, material2)
        // 绘制地图时 y轴取反 这里同步
        circleY.position.set(spot[0], -spot[1], spot[2] + 0.1)
        scene.add(circleY)

        circleYs.push(circleY)
      }


// 移动物体网格对象组
      const moveSpots = []
      /**
       * 线上移动物体
       * */
      function moveSpot(curve) {
        // 线上的移动物体
        const aGeo = new THREE.SphereGeometry(0.4, 0.4, 0.4)
        const aMater = new THREE.MeshPhongMaterial({ color: 0xff0000, side: THREE.DoubleSide })
        const aMesh = new THREE.Mesh(aGeo, aMater)
        // 保存曲线实例
        aMesh.curve = curve
        aMesh._s = 0

        moveSpots.push(aMesh)

        scene.add(aMesh)
      }

       

const createScene = () => {
  scene = new THREE.Scene();
  label3DRenderer = new CSS3DRenderer();
  labelRenderer = new CSS2DRenderer();
};

const createCamera = () => {
  camera = new THREE.PerspectiveCamera(
    100,
    window.innerWidth / window.innerHeight,
    0.1,
    50000
  );
  camera.position.set(0, 0, 300);
};

const createLight = () => {
  const mainLight = new THREE.DirectionalLight(0xffffff, 0.9);
  mainLight.position.set(0, 100, 100);
  scene.add(mainLight);
  // 辅助光源 - 从左侧打来
  const sideLight = new THREE.DirectionalLight(0xffffff, 0.5);
  sideLight.position.set(-100, 50, 0);
  scene.add(sideLight);

  // 环境光 - 均匀提升整体亮度
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.3); // soft white light
  // scene.add(ambientLight);

  // 添加主光源辅助器
  const mainHelper = new THREE.DirectionalLightHelper(mainLight, 25);
  // scene.add(mainHelper);

  // 添加辅助光源辅助器（可选）
  const sideHelper = new THREE.DirectionalLightHelper(sideLight, 20);
  // scene.add(sideHelper);
  // 添加灯光-灯光辅助器
  const light = new THREE.DirectionalLight(0xffffff, 0.9);
  light.position.set(0, 100, 100); // 正面打光
  scene.add(light);
  const helper = new THREE.DirectionalLightHelper(light, 25);
  // scene.add(helper);
};

const createRanderrer = () => {
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // 添加 CSS2DRenderer 的 DOM 元素
  labelRenderer.setSize(window.innerWidth, window.innerHeight);
  labelRenderer.domElement.style.position = 'absolute';
  labelRenderer.domElement.style.top = '0px';
  labelRenderer.domElement.style.left = '0px';
  labelRenderer.domElement.style.pointerEvents = 'none'; // 避免遮挡交互
  document.body.appendChild(labelRenderer.domElement);

  // 初始化 CSS3DRenderer
  label3DRenderer = new CSS3DRenderer();
  label3DRenderer.setSize(window.innerWidth, window.innerHeight);
  label3DRenderer.domElement.style.position = 'absolute';
  label3DRenderer.domElement.style.top = '0px';
  label3DRenderer.domElement.style.left = '0px';
  label3DRenderer.domElement.style.pointerEvents = 'none';
  document.body.appendChild(label3DRenderer.domElement);
};

const createControls = () => {
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableZoom = true; // 启用缩放
  controls.enableRotate = true; // 启用旋转
  controls.enablePan = true; // 禁用平移
  controls.enableDamping = true;
  controls.dampingFactor = 0.09; // 阻尼系数
  controls.rotateSpeed = 0.5; // 旋转速度
};

const animate = () => {
  requestAnimationFrame(animate);

  const time = performance.now() * 0.0002; // 控制速度

  if (zooming) {
    if (zoomStartTime === null) {
      // 使用 performance.now() 是为了获得高精度的时间戳。
      zoomStartTime = performance.now();
    }
    // 已过去多少毫秒。
    const elapsed = performance.now() - zoomStartTime;
    // 是一个介于 0 到 1 的值，表示动画进度
    const t = Math.min(elapsed / zoomDuration, 1); // 归一化时间

    // 相机位置插值
    // 将相机当前位置逐步靠近 (0, 100, 100)。
    camera.position.lerp(new THREE.Vector3(100, 50, 80), t);
    // 让 OrbitControls 始终看向 (0, 0, 0)。
    controls.target.lerp(new THREE.Vector3(91, 2, 42), t); // 最终目标点

    if (t === 1) {
      zooming = false; // 运镜完成
    }
  }

  scene.traverse((child) => {
    if (child.isCSS3DObject && child.isBillboard) {
      child.lookAt(camera.position); // 面向相机
    }

    if (
      child.isMesh &&
      child.userData.targetHeight !== undefined &&
      child.userData.growing
    ) {
      const now = performance.now();
      const delay = 1000; // 动画持续时间（毫秒）

      if (now >= child.userData.startGrowTime) {
        const elapsed = now - child.userData.startGrowTime;
        const t = Math.min(elapsed / delay, 1); // 归一化时间 [0 ~ 1]

        const currentHeight = child.userData.targetHeight * t;

        // 更新几何体（或使用 scale 更高效）
        child.scale.y = currentHeight / 0.1; // Cylinder 默认高度是 0.1
        child.position.z = currentHeight / 2; // 保持底部不动，调整中心位置
        if (t >= 1) {
          child.userData.growing = false; // 动画完成
        }
      }
    }

    if (
      child.isMesh &&
      child.material.uniforms &&
      child.material.uniforms.time
    ) {
      child.material.uniforms.time.value = time;
    }

    // 新增：查找带有涟漪材质的 mesh 并更新
    if (
      child.material instanceof THREE.ShaderMaterial &&
      child.material.uniforms.time
    ) {
      child.material.uniforms.time.value = time;
    }

    if (
      child.material &&
      child.material.uniforms &&
      child.material.uniforms.time
    ) {
      child.material.uniforms.time.value = performance.now() * 0.001;
    }
  });

  scene.traverse((obj) => {
    if (obj.isCSS3DObject && obj.isBillboard) {
      obj.lookAt(camera.position); // 面向相机
    }
  });

  controls.update();
  if (imgFloor1 && imgFloor1?.rotation) {
    imgFloor1.rotation.z += 0.01;
  }
  if (imgFloor2 && imgFloor2?.rotation) {
    imgFloor2.rotation.z += 0.01;
  }

  // imgFloor3.rotation.z += 0.01;
  labelRenderer.render(scene, camera);
  label3DRenderer.render(scene, camera); // 渲染 3D 标签
  renderer.render(scene, camera);
};

// 工具类
</script>

<style scoped></style>
